package com.qf.smartdevice.service.Impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qf.smartdevice.cache.CategoriesCache;
import com.qf.smartdevice.constans.ResultCode;
import com.qf.smartdevice.event.CategoryCacheChangeEvent;
import com.qf.smartdevice.exceptions.AddDataException;
import com.qf.smartdevice.mapper.CategoriesMapper;
import com.qf.smartdevice.pojo.Categories;
import com.qf.smartdevice.service.ICategoriesService;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.sound.midi.Soundbank;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Transactional
public class CategoriesImpl implements ICategoriesService {
    @Autowired
    private CategoriesMapper categoriesMapper;
    @Autowired
    private CategoriesCache categoriesCache;
    @Autowired
    private ApplicationContext context;
    @Autowired
    private CategoryCacheChangeEvent event;

    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
    @Override
    public PageInfo<Categories> findAll(int page, int limit, String categoryname, Long status) {
//        PageHelper.startPage(page, limit);
        PageInfo<Categories> pageInfo = null;

        List<Categories> allData = categoriesCache.getAllData();//缓存中如果没有数据 不查数据库 容易造成缓存穿透问题

        List<Categories> categoriesList = allData.stream().filter(categories -> {
            boolean isFetchaName = true;
            boolean isFetchStatus = true;
            String categoryname1 = categories.getCategoryname();
            Long status1 = categories.getStatus();

            if (!StringUtils.isEmpty(categoryname)) {
//                代表传递了分类的名字
                isFetchaName = categoryname1.contains(categoryname);//判断分类的名字中 是否包含传递的名字
            }
            if (status != null && -100 != status) {//如果传递了状态 并且不是默认的状态
                isFetchStatus = status == status1;
            }
            return isFetchaName && isFetchStatus;// stream 的 filter 要求返回一个Boolean  我们返回的就是
        }).collect(Collectors.toList());

        //=================华丽的分割线,准备切割符合条件的集合===================
//            裁剪集合   下标开始到结束
        int start_index = 0;

        int last_index = limit;//防止第一页没有数据  默认写limit 到10
        if (page * limit >= categoriesList.size()) {// 为了防止出现在切割集合的时候出现数组越界
            last_index = categoriesList.size();// 如果超出了总长度 则最后的一个切割下标就是总长度
        } else {
            last_index = page * limit;// 在不超过当前页情况下就是当前页*每页的数量
        }
        if ((page - 1) * limit >= categoriesList.size()) {
            //起点超出查询范围 直接返回空数据
            pageInfo = new PageInfo<>();
            return pageInfo;
        }
//        切割集合  上面的代码都是怕越界而作的判断
        List<Categories> categories = categoriesList.subList((page - 1) * limit, last_index);
        pageInfo = new PageInfo<>(categories);
        pageInfo.setTotal(categoriesList.size());//设置总长度为符合条件的集合的长度
        return pageInfo;
//        }
//        List<Categories> all = categoriesMapper.findAll();

    }

    @Override
    public void addCategories(Categories categories) {

        if (categories == null || categories.isNull()) {
            throw new AddDataException("数据不能为空", ResultCode.NULL_DATA);
        }

        int i = categoriesMapper.addCategories(categories);

//        更新缓存 如果在这里直接操作缓存 万一出现异常会导致事务回滚，添加失败 更新缓存应该要影响添加数据吗？
//        经过分析发现  即便更新缓存失败 也不应该回滚事务 也就是说这两个是完全独立的操作
//        EVENT 事件

        context.publishEvent(event);//发送事件
    }

    @Override
    public int deleteCategories(Integer[] id) {

        int i = categoriesMapper.deleteCategories(id);
        System.out.println("service" + i);
        categoriesCache.onEvent(event);
        return i;
    }

    @Override
    public int updateById(Categories categories) {

        int i = categoriesMapper.updateById(categories);
        categoriesCache.onEvent(event);
        return i;

    }
}
